#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
# @version: v1.1
# @author : cd
# @Email : 19688513@qq.com
# @Project : new-horizons-engine
# @File : StockYearDataManager.py
# @Software: PyCharm
# @time: 2025/5/30 9:53
# @description : 按年分表的股票数据管理类
"""

import urllib3
import logging
from typing import List, Tuple, Dict, Any, Optional
import pandas as pd
import numpy as np
import sqlite3
from datetime import datetime, timedelta
from tqdm import tqdm

from DatabaseManager import DatabaseManager
from Email.email_service import EmailService
from ExcelExporter import ExcelExporter
from SignalGenerator import SignalGenerator
from StockBasicInfoManager import StockBasicInfoManager
from AKShareDataFetcher import AKShareDataFetcher
from StockPlotter import StockPlotter
from TradeDateManager import TradeDateManager

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 禁用不安全的请求警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


class StockYearDataManager:
    """按年分表的股票数据管理类"""

    def __init__(self, db_manager: DatabaseManager):
        self.db_manager = db_manager
        self.signal_generator = SignalGenerator()
        self.stock_plotter = StockPlotter()
        self.trade_calendar = TradeDateManager(db_manager)
        # 确保年份表存在
        self._ensure_year_tables()

    def _ensure_year_tables(self):
        """确保当前年份和前一年的数据表存在"""
        current_year = datetime.now().year
        years = [current_year - 1, current_year]

        with self.db_manager.get_connection() as conn:
            for year in years:
                table_name = f"stock_data_{year}"
                conn.execute(f'''
                    CREATE TABLE IF NOT EXISTS {table_name} (
                        date TEXT NOT NULL,
                        symbol TEXT NOT NULL,
                        open REAL,
                        close REAL,
                        high REAL,
                        low REAL,
                        volume INTEGER,
                        turnover REAL,
                        amplitude REAL,
                        change_pct REAL,
                        change_amt REAL,
                        turnover_rate REAL,
                        PRIMARY KEY (symbol, date)
                    )
                ''')
                conn.execute(f"CREATE INDEX IF NOT EXISTS idx_{table_name}_date ON {table_name}(date)")
                conn.execute(f"CREATE INDEX IF NOT EXISTS idx_{table_name}_symbol ON {table_name}(symbol)")

    def calculate_moving_averages(self, data: pd.DataFrame) -> pd.DataFrame:
        """计算移动平均指标（支持中英文列名）"""
        if data.empty:
            return data

        # 确定列名映射
        close_col = 'close' if 'close' in data.columns else '收盘'
        volume_col = 'volume' if 'volume' in data.columns else '成交量'

        # 检查必要列是否存在
        if close_col not in data.columns or volume_col not in data.columns:
            logging.warning("缺少必要的收盘价或成交量列，无法计算移动平均线")
            return data

        # 价格均线
        for window in [5, 10, 20, 30, 60, 120]:
            col_name = f'ma{window}'
            if col_name not in data.columns:
                data[col_name] = data[close_col].rolling(window, min_periods=1).mean().round(2)

        # 成交量均线（转换为万手）
        for window in [5, 10, 20, 30, 60, 120]:
            col_name = f'vol_ma{window}'
            if col_name not in data.columns:
                # 转换为万手（1手=100股）
                data[col_name] = (data[volume_col].rolling(window, min_periods=1).mean() / 10000).round(1)

        return data

    def calculate_additional_indicators(self, data: pd.DataFrame) -> pd.DataFrame:
        """计算基于成交量的技术指标（成交量已转换为万手单位）"""
        if data.empty:
            return data

        # 确保成交量列存在
        if 'volume' not in data.columns:
            logging.warning("缺少成交量数据，无法计算技术指标")
            return data

        # 将成交量转换为万手单位
        volume_col = 'volume'
        data['volume_wan'] = data[volume_col] / 10000

        # 计算MACD指标（基于成交量）
        if 'vol_macd' not in data.columns:
            try:
                exp12 = data['volume_wan'].ewm(span=12, adjust=False).mean()
                exp26 = data['volume_wan'].ewm(span=26, adjust=False).mean()
                data['vol_macd'] = exp12 - exp26
                data['vol_signal'] = data['vol_macd'].ewm(span=9, adjust=False).mean()
                data['vol_hist'] = data['vol_macd'] - data['vol_signal']
            except Exception as e:
                logging.warning(f"计算成交量MACD失败: {e}")

        # 计算RSI指标（基于成交量）
        if 'vol_rsi' not in data.columns:
            try:
                delta = data['volume_wan'].diff()
                gain = delta.where(delta > 0, 0)
                loss = -delta.where(delta < 0, 0)

                avg_gain = gain.rolling(window=14).mean()
                avg_loss = loss.rolling(window=14).mean()

                rs = avg_gain / (avg_loss + 1e-8)  # 避免除零
                data['vol_rsi'] = 100 - (100 / (1 + rs))
            except Exception as e:
                logging.warning(f"计算成交量RSI失败: {e}")

        # 计算布林带（基于成交量）
        if 'vol_boll_upper' not in data.columns:
            try:
                sma = data['volume_wan'].rolling(window=20).mean()
                std = data['volume_wan'].rolling(window=20).std()
                data['vol_boll_upper'] = sma + (std * 2)
                data['vol_boll_middle'] = sma
                data['vol_boll_lower'] = sma - (std * 2)
            except Exception as e:
                logging.warning(f"计算成交量布林带失败: {e}")

        # 计算KDJ指标（基于成交量）- 修复版
        if 'vol_k' not in data.columns:
            try:
                # 使用成交量代替价格
                low_min = data['volume_wan'].rolling(window=9, min_periods=1).min()
                high_max = data['volume_wan'].rolling(window=9, min_periods=1).max()
                rsv = ((data['volume_wan'] - low_min) / (high_max - low_min + 1e-8)) * 100

                # 初始化K、D、J列
                k = np.zeros(len(data))
                d = np.zeros(len(data))
                j = np.zeros(len(data))

                # 初始值
                k[0] = 50
                d[0] = 50
                j[0] = 50

                # 计算K、D、J值
                for i in range(1, len(data)):
                    k[i] = (2 / 3) * k[i - 1] + (1 / 3) * rsv.iloc[i]
                    d[i] = (2 / 3) * d[i - 1] + (1 / 3) * k[i]
                    j[i] = 3 * k[i] - 2 * d[i]

                data['vol_k'] = k
                data['vol_d'] = d
                data['vol_j'] = j
            except Exception as e:
                logging.warning(f"计算成交量KDJ失败: {e}")

        return data

    def batch_upsert_data(self, data: pd.DataFrame, symbol: str) -> int:
        """批量更新或插入股票数据"""
        if data.empty:
            logging.warning(f"股票{symbol}批量插入数据为空")
            return 0

        inserted_rows = 0
        try:
            # 确保日期列为字符串格式
            data['date'] = pd.to_datetime(data['date']).dt.strftime('%Y-%m-%d')  # 将日期列转换为字符串格式

            with self.db_manager.get_connection() as conn:
                conn.execute("BEGIN IMMEDIATE")

                # 按年份分组处理
                data['year'] = pd.to_datetime(data['date']).dt.year
                for year, group in data.groupby('year'):
                    table_name = f"stock_data_{year}"
                    records = self._prepare_records(group, symbol)

                    if not records:
                        continue

                    # 创建SQL语句 - 匹配DatabaseManager中的表结构
                    insert_sql = f'''
                        INSERT INTO {table_name} (
                            date, symbol, open, close, high, low, volume, 
                            turnover, amplitude, change_pct, change_amt, turnover_rate
                        ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
                        ON CONFLICT(symbol, date) DO UPDATE SET
                            open=excluded.open,
                            close=excluded.close,
                            high=excluded.high,
                            low=excluded.low,
                            volume=excluded.volume,
                            turnover=excluded.turnover,
                            amplitude=excluded.amplitude,
                            change_pct=excluded.change_pct,
                            change_amt=excluded.change_amt,
                            turnover_rate=excluded.turnover_rate
                    '''
                    conn.executemany(insert_sql, records)
                    inserted_rows += len(records)

                conn.commit()
                logging.info(f"股票{symbol}成功插入/更新 {inserted_rows} 条记录")
        except sqlite3.Error as e:
            logging.error(f"股票{symbol}批量插入失败: {e}", exc_info=True)
            inserted_rows = 0
        return inserted_rows

    def _prepare_records(self, data: pd.DataFrame, symbol: str) -> list:
        """准备批量插入的记录列表"""
        records = []
        required_columns = [
            'date', 'open', 'close', 'high', 'low', 'volume',
            'turnover', 'amplitude', 'change_pct', 'change_amt', 'turnover_rate'
        ]

        # 验证必要列是否存在
        missing_cols = [col for col in required_columns if col not in data.columns]
        if missing_cols:
            logging.error(f"缺少必要列: {missing_cols}")
            return records

        try:
            for _, row in data.iterrows():
                # 使用英文列名访问数据
                record = (
                    row['date'],  # 日期
                    symbol,  # 股票代码
                    row['open'],  # 开盘价
                    row['close'],  # 收盘价
                    row['high'],  # 最高价
                    row['low'],  # 最低价
                    row['volume'],  # 成交量
                    row['turnover'],  # 成交额
                    row['amplitude'],  # 振幅
                    row['change_pct'],  # 涨跌幅
                    row['change_amt'],  # 涨跌额
                    row['turnover_rate']  # 换手率
                )
                records.append(record)
        except KeyError as e:
            logging.error(f"准备记录失败: {e}, 行数据: {row}")
        return records

    def query_stock_data(self, symbol: str, start_date: str, end_date: str) -> pd.DataFrame:
        """查询股票历史数据并计算移动平均线"""
        try:
            # 解析日期并获取年份范围
            start_dt = pd.to_datetime(start_date)
            end_dt = pd.to_datetime(end_date)
            start_year = start_dt.year
            end_year = end_dt.year
        except Exception as e:
            logging.error(f"日期格式错误: {e}")
            return pd.DataFrame()

        results = []
        conn = None
        try:
            conn = self.db_manager.get_connection()
            for year in range(start_year, end_year + 1):
                table_name = f"stock_data_{year}"
                try:
                    query = f'''
                                        SELECT s.date, s.symbol, s.open, s.close, s.high, s.low, s.volume,
                                               s.turnover, s.amplitude, s.change_pct, s.change_amt, s.turnover_rate,
                                               b.stock_name, b.total_market_value, b.circulating_market_value, 
                                               b.industry, b.listing_date, b.total_shares, b.circulating_shares,
                                               b.rating_agency, b.rating, b.rating_quarter, b.market_type, 
                                               b.last_updated  
                                        FROM {table_name} AS s
                                        JOIN stock_basic_info AS b ON s.symbol = b.stock_code  
                                        WHERE s.symbol = ? AND s.date BETWEEN ? AND ?  
                                        ORDER BY s.date  
                                    '''
                    cursor = conn.execute(query, (symbol, start_date, end_date))
                    year_results = cursor.fetchall()
                    if year_results:
                        results.extend(year_results)
                except sqlite3.OperationalError as e:
                    logging.warning(f"查询表 {table_name} 失败: {e}")
                    continue
        except Exception as e:
            logging.error(f"数据库查询失败: {e}")
        finally:
            if conn:
                conn.close()

        # 处理查询结果
        if not results:
            logging.warning(f"未查询到股票数据: symbol={symbol}, start={start_date}, end={end_date}")
            return pd.DataFrame()

        try:
            # 创建DataFrame
            columns = [
                'date', 'symbol', 'open', 'close', 'high', 'low', 'volume',
        'turnover', 'amplitude', 'change_pct', 'change_amt', 'turnover_rate',
        'stock_name', 'total_market_value', 'circulating_market_value',
        'industry', 'listing_date', 'total_shares', 'circulating_shares',
        'rating_agency', 'rating', 'rating_quarter', 'market_type',
        'last_updated'
            ]
            df = pd.DataFrame(results, columns=columns)

            # 转换日期类型
            df['date'] = pd.to_datetime(df['date'])
            df.sort_values('date', inplace=True)

            # 计算技术指标
            df = self.calculate_additional_indicators(df)
            df = self.calculate_moving_averages(df)

            return df

        except Exception as e:
            logging.error(f"数据处理失败: {e}")
            return pd.DataFrame()

    def clear_year_data(self, year: int) -> None:
        """清空指定年份的数据"""
        table_name = f"stock_data_{year}"
        try:
            with self.db_manager.get_connection() as conn:
                conn.execute(f"DELETE FROM {table_name}")
                conn.commit()
                logging.info(f"{year} 年股票数据已清空")
        except sqlite3.OperationalError as e:
            logging.warning(f"表 {table_name} 不存在: {e}")

    def fetch_combined_data(self, batch_size: int = 50) -> int:
        """获取并存储所有股票的历史数据（根据上市日期确定开始时间）"""
        logging.info("开始获取并存储所有股票历史数据...")

        # 创建股票基本信息管理实例
        stock_manager = StockBasicInfoManager(self.db_manager)
        data_fetcher = AKShareDataFetcher(
            max_retries=3,
            retry_delay=5,
            request_delay=1
        )

        # 获取符合条件的股票代码（包含上市日期）
        filtered_stock_codes_df = stock_manager.get_stock_codes()
        if filtered_stock_codes_df.empty:
            logging.info("股票基本信息未初始化，正在初始化...")
            stock_manager.initialize_stock_database()
            filtered_stock_codes_df = stock_manager.get_stock_codes()

        if filtered_stock_codes_df.empty:
            logging.error("无法获取股票代码列表")
            return 0

        # 转换为股票代码和上市日期的元组列表
        stock_info = filtered_stock_codes_df[['stock_code', 'listing_date']].to_records(index=False).tolist()
        total_stocks = len(stock_info)
        logging.info(f"共发现 {total_stocks} 只股票需要处理")

        # 使用tqdm创建进度条
        from tqdm import tqdm
        inserted_total = 0
        failed_stocks = []

        # 创建tqdm进度条
        with tqdm(total=total_stocks, desc="🚀 获取股票历史数据", unit="股") as pbar:
            # 分批处理股票
            for i in range(0, total_stocks, batch_size):
                batch = stock_info[i:i + batch_size]
                pbar.set_description(f"处理批次 {i // batch_size + 1}/{(total_stocks - 1) // batch_size + 1}")

                for stock_code, listing_date in batch:
                    try:
                        # 处理上市日期格式（确保是YYYYMMDD格式）
                        if isinstance(listing_date, str):
                            # 确保是8位数字
                            if len(listing_date) == 8 and listing_date.isdigit():
                                start_date = "20070101"
                                # 如果上市日期在2007年之后，使用上市日期作为开始日期
                                if listing_date > "20070101":
                                    start_date = listing_date
                            else:
                                # 日期格式无效，使用默认值
                                start_date = "20070101"
                                logging.warning(f"股票{stock_code}的上市日期格式无效: {listing_date}")
                        else:
                            # 非字符串类型（如None或datetime），使用默认值
                            start_date = "20070101"

                        end_date = datetime.now().strftime("%Y%m%d")

                        # 获取历史数据
                        hist_data = data_fetcher.fetch_historical_data_dc(
                            symbol=stock_code,
                            start_date=start_date,
                            end_date=end_date,
                            adjust="qfq",  # 前复权
                            max_retries=3,
                            retry_delay=10,
                            request_delay=2
                        )

                        if hist_data.empty:
                            logging.warning(f"股票{stock_code}未获取到历史数据")
                            failed_stocks.append(stock_code)
                            pbar.update(1)
                            continue

                        # 存储数据
                        inserted = self.batch_upsert_data(hist_data, stock_code)
                        inserted_total += inserted
                        logging.debug(f"股票{stock_code}存储了 {inserted} 条记录")

                    except Exception as e:
                        logging.error(f"处理股票{stock_code}时出错: {str(e)}")
                        failed_stocks.append(stock_code)

                    # 更新进度条
                    pbar.update(1)

        # 结果统计
        success_count = total_stocks - len(failed_stocks)
        logging.info(f"所有股票历史数据处理完成! 共处理 {total_stocks} 只股票")
        logging.info(f"成功: {success_count}, 失败: {len(failed_stocks)}, 共存储 {inserted_total} 条记录")

        if failed_stocks:
            logging.warning(
                f"以下股票处理失败: {', '.join(failed_stocks[:10])}{'...' if len(failed_stocks) > 10 else ''}")

        return inserted_total

    def generate_signals(self, df: pd.DataFrame) -> Dict[str, Any]:
        """生成交易信号"""
        return self.signal_generator.generate_signals(df)

    def plot_stock_analysis(self, df: pd.DataFrame, symbol: str, start_date: str, end_date: str) -> Optional[str]:
        """绘制股票分析图表"""
        return self.stock_plotter.plot_stock_analysis(df, symbol, start_date, end_date)

    def fetch_and_generate_signals(self, target_date):
        """获取所有股票信号并返回深圳和上海市场的信号列表"""
        # 创建股票基本信息管理实例
        stock_manager = StockBasicInfoManager(self.db_manager)
        # 获取深圳和上海股票代码
        sz_stock_codes_df = stock_manager.get_stock_codes(['sz'])
        sh_stock_codes_df = stock_manager.get_stock_codes(['sh'])

        start_date, end_date = self.trade_calendar.get_offset_trade_dates(target_date, 120)
        end_date = target_date
        # 准备一个用于存储所有信号的列表
        sz_signals = []
        sh_signals = []

        # 使用tqdm显示进度
        sz_progress_bar = tqdm(total=len(sz_stock_codes_df), desc="分析深圳股票信号", unit="只")
        sh_progress_bar = tqdm(total=len(sh_stock_codes_df), desc="分析上海股票信号", unit="只")

        # 处理深圳股票
        for stock_code in sz_stock_codes_df['stock_code'].tolist():
            sz_progress_bar.set_description(f"分析深圳股票 {stock_code}")
            try:
                # 获取数据
                stock_data = self.query_stock_data(stock_code, start_date, end_date)
                if not stock_data.empty:
                    signals = self.generate_signals(stock_data)

                    # 检查是否有信号记录
                    if 'signals_list' in signals and signals['signals_list']:
                        # 查找目标日期的信号
                        for record in signals['signals_list']:
                            if record['date'] == target_date:
                                sz_signals.append(record)
            except Exception as e:
                logging.error(f"处理深圳股票 {stock_code} 时出错: {str(e)}")
            finally:
                sz_progress_bar.update(1)
        # 关闭进度条
        sz_progress_bar.close()

        # 处理上海股票
        for stock_code in sh_stock_codes_df['stock_code'].tolist():
            sh_progress_bar.set_description(f"分析上海股票 {stock_code}")
            try:
                # 获取数据
                stock_data = self.query_stock_data(stock_code, start_date, end_date)
                if not stock_data.empty:
                    signals = self.generate_signals(stock_data)

                    # 检查是否有信号记录
                    if 'signals_list' in signals and signals['signals_list']:
                        # 查找目标日期的信号
                        for record in signals['signals_list']:
                            if record['date'] == target_date:
                                sh_signals.append(record)
            except Exception as e:
                logging.error(f"处理上海股票 {stock_code} 时出错: {str(e)}")
            finally:
                sh_progress_bar.update(1)
        # 关闭进度条
        sh_progress_bar.close()


        logging.info(f"深圳市场发现 {len(sz_signals)} 个有效信号（目标日期: {target_date}）")
        logging.info(f"上海市场发现 {len(sh_signals)} 个有效信号（目标日期: {target_date}）")

        return {
            'sz_signals': sz_signals,
            'sh_signals': sh_signals,
            'target_date': target_date
        }



if __name__ == "__main__":
    # 创建数据库管理器实例
    db_manager = DatabaseManager()
    # 创建Excel导出器实例
    exporter = ExcelExporter()
    # 创建股票数据管理实例
    data_manager = StockYearDataManager(db_manager)
    # print(f"深圳市场 信号:")
    # data_manager.fetch_combined_data()
    # print(f"深圳市场  信号:")


    target_date = '2025-06-06'
    signals = data_manager.fetch_and_generate_signals(target_date)
    # 生成信号报告
    report_path = exporter.export_signals_report(signals, target_date)
    email_service = EmailService()
    html_content = """
    <h1>每日推荐</h1>
    <p>
        signal_vol: 1: 成交量双均线条件：成交量接近5日均量且低于60日均量的70%<br>
        signal_price: 2: 价格均线多头排列：5日>10日>20日均线，且5日均线上扬<br>
        signal_vol_break: 3: 量能趋势突破：5日成交量均线上穿20日成交量均线<br>
        signal_trend: 4: 趋势延续验证：成交量均线多头排列(5>20>60)且价格高于3日均价<br>
        signal_volume_price: 5: 量价齐升：成交量放大10%以上，阳线且突破前日高点<br>
        signal_volatility: 6: 波动率适中：14日ATR处于近1年30%-70%分位之间<br>
        signal_rsi: 7: 价格RSI超卖：价格RSI低于其14日均值减1.5倍标准差<br>
        signal_vol_macd: 8: 成交量MACD金叉：成交量MACD上穿信号线<br>
        signal_vol_rsi: 9: 成交量RSI超卖：成交量RSI < 30<br>
        signal_vol_boll: 10: 成交量布林带收窄：带宽小于20日均宽的70%，且成交量在通道内<br>
        signal_vol_kdj: 11: 成交量KDJ金叉：K线上穿D线且J值>20<br>
        量价共振: 12: 量价齐升+成交量MACD金叉+价格RSI>50<br>
        底部反转信号: 13: 成交量RSI超卖+成交量KDJ金叉+价格RSI<40<br>
    </p>
    """

    recommendation_sent = email_service.send_daily_recommendation(
        html_content=html_content,
        email_title="每日推荐服务",
        subject="每日推荐",
        delay_seconds=5,  # 每组之间等待5秒
        attachment_path=report_path  # 附件路径
    )
    logging.info(f"每日推荐发送{'成功' if recommendation_sent else '部分失败'}")

    # 处理深圳市场信号
    print(f"深圳市场 {target_date} 信号:")
    combined_sz_signals = {}
    for signal in signals['sz_signals']:  # 前5个最强信号
        code = signal['stock_code']
        if code not in combined_sz_signals:
            combined_sz_signals[code] = {
                'date': signal['date'],
                'stock_name': signal['stock_name'],
                'signals': []
            }
        combined_sz_signals[code]['signals'].append(f"{signal['signal_name']} (描述: {signal.get('description')})")

    # 打印合并后的信号
    for code, info in combined_sz_signals.items():
        combined_signals = "; ".join(info['signals'])
        print(f"{info['date']}  {code} {info['stock_name']}: {combined_signals}")

    # 处理上海市场信号
    print(f"\n上海市场 {target_date} 信号:")
    combined_sh_signals = {}
    for signal in signals['sh_signals']:  # 前5个最强信号
        code = signal['stock_code']
        if code not in combined_sh_signals:
            combined_sh_signals[code] = {
                'date': signal['date'],
                'stock_name': signal['stock_name'],
                'signals': []
            }
        combined_sh_signals[code]['signals'].append(f"{signal['signal_name']} (描述: {signal.get('description')})")

    # 打印合并后的信号
    for code, info in combined_sh_signals.items():
        combined_signals = "; ".join(info['signals'])
        print(f"{info['date']}  {code} {info['stock_name']}: {combined_signals}")

    # # 查询股票数据
    # end_date = datetime.now().strftime("%Y-%m-%d")
    # start_date = (datetime.now() - timedelta(days=250)).strftime("%Y-%m-%d")
    #
    # test_symbol = "000001"  # 平安银行
    # logging.info(f"查询 {test_symbol} 从 {start_date} 到 {end_date} 的数据...")
    #  # 获取数据
    # stock_data = data_manager.query_stock_data(test_symbol, start_date, end_date)
    #
    # if not stock_data.empty:
    #     # 显示前5条数据
    #     logging.info(
    #         f"查询结果 (前5条):\n{stock_data[['date', 'open', 'close', 'high', 'low', 'volume']].head(5).to_string(index=False)}")
    #
    #     # 显示最后5条数据
    #     logging.info(
    #         f"查询结果 (最后5条):\n{stock_data[['date', 'open', 'close', 'high', 'low', 'volume']].tail(5).to_string(index=False)}")
    #
    #     # # 显示移动平均线
    #     # logging.info(f"移动平均线 (最后5天):")
    #     # logging.info(f"MA5: {stock_data['ma5'].iloc[-5:].values.round(2)}")
    #     # logging.info(f"MA20: {stock_data['ma20'].iloc[-5:].values.round(2)}")
    #     # logging.info(f"成交量MA5 (万手): {stock_data['vol_ma5'].iloc[-5:].values.round(1)}")
    #     #
    #     # # 显示基于成交量的技术指标
    #     # if 'vol_macd' in stock_data.columns:
    #     #     logging.info(f"成交量MACD指标 (最后5天):")
    #     #     logging.info(f"MACD: {stock_data['vol_macd'].iloc[-5:].values.round(4)}")
    #     #     logging.info(f"Signal: {stock_data['vol_signal'].iloc[-5:].values.round(4)}")
    #     #     logging.info(f"Hist: {stock_data['vol_hist'].iloc[-5:].values.round(4)}")
    #     #
    #     # # 显示成交量RSI指标
    #     # if 'vol_rsi' in stock_data.columns:
    #     #     logging.info(f"成交量RSI指标 (最后5天): {stock_data['vol_rsi'].iloc[-5:].values.round(2)}")
    #     #
    #     # # 显示成交量布林带指标
    #     # if 'vol_boll_upper' in stock_data.columns:
    #     #     logging.info(f"成交量布林带指标 (最后5天):")
    #     #     logging.info(f"上轨: {stock_data['vol_boll_upper'].iloc[-5:].values.round(2)}")
    #     #     logging.info(f"中轨: {stock_data['vol_boll_middle'].iloc[-5:].values.round(2)}")
    #     #     logging.info(f"下轨: {stock_data['vol_boll_lower'].iloc[-5:].values.round(2)}")
    #     #
    #     # # 显示成交量KDJ指标
    #     # if 'vol_k' in stock_data.columns:
    #     #     logging.info(f"成交量KDJ指标 (最后5天):")
    #     #     logging.info(f"K值: {stock_data['vol_k'].iloc[-5:].values.round(2)}")
    #     #     logging.info(f"D值: {stock_data['vol_d'].iloc[-5:].values.round(2)}")
    #     #     logging.info(f"J值: {stock_data['vol_j'].iloc[-5:].values.round(2)}")
    #
    #     # 获取信号
    #     signals = data_manager.generate_signals(stock_data)
    #
    #     # 访问信号数据
    #     print("==== 信号摘要 ====")
    #     for summary in signals['signals_summary']:
    #         print(f"信号{summary['signal_id']}: {summary['trigger_count']}次触发, 最后触发: {summary['last_trigger']}")
    #         print(f"  描述: {summary['description']}")
    #
    #     print("\n==== 详细信号记录 ====")
    #     for record in signals['signals_list']:  # 打印前5个信号
    #         print(f"{record['date']} 股票{record['stock_code']} {record['stock_name']} ({record['industry']})")
    #         print(f"  评级: {record['rating']}, 信号ID: {record['signal_id']} - {record['signal_name']}")
    #         print(f"  收盘价: {record['close_price']}, 成交量: {record['volume']}")
    #
    #         # 打印技术指标（如果存在）
    #         indicators = []
    #         if record['price_rsi'] is not None:
    #             indicators.append(f"价格RSI: {record['price_rsi']}")
    #         if record['vol_rsi'] is not None:
    #             indicators.append(f"成交量RSI: {record['vol_rsi']}")
    #         if record['vol_macd'] is not None:
    #             indicators.append(f"成交量MACD: {record['vol_macd']}")
    #         if record['vol_k'] is not None and record['vol_d'] is not None:
    #             indicators.append(f"成交量KDJ: K={record['vol_k']}, D={record['vol_d']}")
    #
    #         if indicators:
    #             print(f"  技术指标: {', '.join(indicators)}")
    #
    #         print(f"  信号描述: {record['description']}")
    #         print("-" * 60)  # 分隔线
    #     # 绘制图表
    #     # plot_filename = data_manager.plot_stock_analysis(stock_data, test_symbol, start_date, end_date)
    #     # if plot_filename:
    #     #     logging.info(f"股票分析图已保存到: {plot_filename}")
    # else:
    #     logging.warning("未查询到股票数据")